package com.yboot.starter.mybatis.core.validator;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.yboot.starter.mybatis.core.annotation.TableIndexes;
import com.yboot.starter.mybatis.core.annotation.UniqueIndex;
import com.yboot.starter.common.core.exception.BusinessException;
import lombok.AllArgsConstructor;
import org.apache.ibatis.session.SqlSession;
import org.springdoc.core.providers.JavadocProvider;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 默认的表索引校验接口实现
 *
 */
@AllArgsConstructor
public class DefaultTableIndexValidatorApi implements TableIndexValidatorApi {

    private final SqlSession sqlSession;

    private final JavadocProvider javadocProvider;

    @Override
    public <T> void validate(T target, Class<T> clazz, boolean update) throws BusinessException {

        if (target == null || clazz == null) {
            return;
        }

        // 1. 准备工作

        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);

        TableFieldInfo logicDeleteFieldInfo = tableInfo.getLogicDeleteFieldInfo();

        Map<String, String> propertyColumnMap = tableInfo.getFieldList().stream().collect(Collectors.toMap(TableFieldInfo::getProperty, TableFieldInfo::getColumn));

        // 2. 获取注解
        TableIndexes tableIndexesAnnotation = clazz.getAnnotation(TableIndexes.class);
        if (tableIndexesAnnotation == null || tableIndexesAnnotation.indexes() == null || tableIndexesAnnotation.indexes().length == 0) {
            return;
        }

        BaseMapper<T> mapper = SqlHelper.getMapper(clazz, sqlSession);

        UniqueIndex[] indexes = tableIndexesAnnotation.indexes();
        for (UniqueIndex index : indexes) {
            String[] fieldNames = index.fieldNames();
            String message = index.message();
            if (fieldNames == null || fieldNames.length == 0) {
                continue;
            }

            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            String[] values = new String[fieldNames.length];
            // 处理常规字段
            for (int i = 0; i < fieldNames.length; i++) {
                String fieldName = fieldNames[i];

                Field field = ReflectUtil.getField(clazz, fieldName);
                if (field == null) {
                    continue;
                }

                String fieldJavadoc = javadocProvider.getFieldJavadoc(field);
                Object fieldValue = ReflectUtil.getFieldValue(target, fieldName);
                values[i] = fieldJavadoc;

                queryWrapper.eq(propertyColumnMap.get(fieldName), fieldValue);
            }

            // 处理逻辑删除字段
            if (logicDeleteFieldInfo != null) {
                queryWrapper.eq(logicDeleteFieldInfo.getColumn(), "0");
            }

            // 判断是否是数据更新
            if (update) {
                queryWrapper.ne(tableInfo.getKeyColumn(), ReflectUtil.getFieldValue(target, tableInfo.getKeyProperty()));
            }

            // 查询数据库
            Long count = mapper.selectCount(queryWrapper);

            if (count > 0) {
                if (StringUtils.hasLength(message)) {
                    throw new BusinessException(message);
                } else {
                    throw new BusinessException(String.join(",", values));
                }
            }
        }
    }

}
